package httpcommon

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"

	"strings"

	lg "gitee.com/bm_guangge/bm_common/log"
)

const (
	TOKEN_EXPIRES  = -20 // token 过期
	RESPONSE_ERROR = -10 // 请求错误
	RESPONSE_OK    = 0   // 请求成功
)

var Mux map[string]func(w http.ResponseWriter, r *http.Request)

type MyHandler struct {
	// mux := make(map[string]func(http.ResponseWriter, *http.Request))
}

// 添加路由
func AddRolter(r string, f func(http.ResponseWriter, *http.Request)) {
	if Mux == nil {
		Mux = make(map[string]func(http.ResponseWriter, *http.Request), 0)
	}

	lg.ILogger.Println("r:", r)
	Mux[r] = f //.(func(w http.ResponseWriter, r *http.Request))
}

func (lh *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path
	// lg.ILogger.Println("ServeHTTP:", path, "method:", r.Method, "host:", r.Host)

	if r.Method == http.MethodOptions {
		Cors(w)
		w.WriteHeader(http.StatusOK)
		// w.Write()
		return
	} else if r.Method == http.MethodPost || r.Method == http.MethodGet {
		// lg.ILogger.Println("urlPath:", r.URL.Path, "len:", len(Mux))
		if h, ok := Mux[path]; ok {
			Cors(w)
			h(w, r)
			return
		}
	}

	w.WriteHeader(http.StatusForbidden)
}

func Cors(w http.ResponseWriter) {
	// w.Header().Set("Access-Control-Allow-Origin", "*")             //允许访问所有域
	// w.Header().Add("Access-Control-Allow-Headers", "Content-Type") //header的类型

	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
	w.Header().Add("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, token, total, a")
	w.Header().Add("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Cache-Control, Content-Language, Content-Type")
	w.Header().Add("Access-Control-Allow-Credentials", "true")

	// lg.ILogger.Println("cors header!")
}

func WriteError(w http.ResponseWriter, r *http.Request, rd interface{}) {
	Cors(w)
	b, e := json.Marshal(rd)
	if e != nil {
		er := fmt.Sprintf(`{"code":%d, "msg":"json序列化错误"}`, 401)
		w.Write([]byte(er))
		return
	}

	_, err := w.Write(b)
	if err != nil {
		lg.ELogger.Println("WriteError Write error:", err.Error())
	}
}

func DefaultQuery(url *url.URL, key, defaultValue string) string {
	v := url.Query().Get(key)
	if len(v) == 0 {
		return defaultValue
	}

	return v
}

func QueryNum(url *url.URL, key string) (int, error) {
	v := url.Query().Get(key)
	if len(v) == 0 {
		return -1, nil
	}

	iv, err := strconv.Atoi(v)
	if err != nil {
		return -1, err
	}

	return iv, nil
}

type ResponeBase struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
}

type ResponDData struct {
	Time string `json:"time"`
}
type ResponeData struct {
	ResponeBase
	Data ResponDData `json:"data"`
}

func ParseJsonBody(w http.ResponseWriter, r *http.Request, v interface{}) error {
	is_json := false
	for _, t := range r.Header["Content-Type"] {
		ct := strings.ToLower(t)
		if strings.Contains(ct, "application/json") {
			is_json = true
		}
	}

	body, err := getRequestBody(w, r)
	if err != nil {
		lg.ELogger.Println("getRequestBody:", err)
		return err
	}

	if is_json {
		err = parseJson(body, v)
		return err
	}

	return errors.New("not json")
}

func getRequestBody(w http.ResponseWriter, r *http.Request) ([]byte, error) {
	body, err := ioutil.ReadAll(r.Body)

	if err != nil {

		lg.ELogger.Println("read body error!")
		return body, err
	}
	return body, err
}

func parseJson(d []byte, v interface{}) error {
	err := json.Unmarshal(d, v)
	if err != nil {
		lg.ELogger.Println("parse json error:", err)
		lg.ELogger.Println("data:", string(d))
		return err
	}
	return nil
}
